/*
 * Copyright 2011-2018 ijym-lee
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package me.ijleex.openapi.oauth.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.BeanIds;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.Assert;

import me.ijleex.openapi.oauth.service.UserService;

/**
 * 配置 安全校验（GlobalAuthenticationConfigurerAdapter）
 *
 * <p>https://www.jianshu.com/p/a8e317e82425</p>
 *
 * @author liym
 * @since 2018-11-30 15:49 新建
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    private final UserService userService;

    /**
     * 构造器注入
     *
     * @param userService 注入的对象：用户服务
     */
    @Autowired
    public WebSecurityConfiguration(UserService userService) {
        Assert.notNull(userService, "UserService required");
        this.userService = userService;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        auth.userDetailsService(this.userService).passwordEncoder(passwordEncoder);
    }

    /**
     * 生成认证管理器，用于支持 grant_type="password" 模式
     */
    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 设置不拦截规则
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**", "/css/**", "/images/**", "/druid/**");
    }

    // @Override
    // protected void configure(HttpSecurity http) throws Exception {
    //     http.authorizeRequests()
    //             // 任何请求，登录后可以访问
    //             .anyRequest().permitAll()
    //             // 配置登录 URL、默认 URL、登录成功与登录失败跳转的 URL
    //             .and().formLogin().loginPage("/login").defaultSuccessUrl("/").successForwardUrl("/index2").failureForwardUrl("/fail").permitAll()
    //             // 注销行为任意访问
    //             .and().logout().permitAll()
    //             // 设置拒绝访问提示 URL
    //             .and().exceptionHandling().accessDeniedPage("/login?illegal")
    //             .and().csrf().disable().anonymous().disable();
    // }

    /**
     * 不拦截 OAuth 要开放的资源
     *
     * @see ResourceServerConfiguration#configure(HttpSecurity)
     */
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.requestMatchers()
                .antMatchers("/oauth/**", "/login/**", "/logout/**")
                .and()
                .authorizeRequests()
                .antMatchers("/oauth/**").authenticated()
                .and()
                .formLogin().permitAll();
    }

}
